

__author__="kamillo"
__date__ ="$2009-11-08 22:54:54$"


import os
from copy import deepcopy
from time import clock

from numpy import *
from svqbak import SVQ
import wx
from wx.lib.floatcanvas import FloatCanvas
from wx.lib.floatcanvas import NavCanvas
from wx.lib.floatcanvas.Utilities import *
ID_DRAW_BUTTON = 100
ID_QUIT_BUTTON = 101
ID_CLEAR_BUTTON = 103
ID_ZOOM_IN_BUTTON = 104
ID_ZOOM_OUT_BUTTON = 105
ID_ZOOM_TO_FIT_BUTTON = 110
ID_MOVE_MODE_BUTTON = 111
ID_TEST_BUTTON = 112

ID_ABOUT_MENU = 200
ID_EXIT_MENU  = 201
ID_ZOOM_IN_MENU = 202
ID_ZOOM_OUT_MENU = 203
ID_ZOOM_TO_FIT_MENU = 204
ID_DRAWTEST_MENU = 205
ID_DRAWMAP_MENU = 206
ID_CLEAR_MENU = 207
ID_OPEN = 208
ID_DIR = 209
ID_RUNCBSVQ_MENU = 210


ID_TEST = 500


class DrawFrame(wx.Frame):
    def __init__(self,parent, id,title,position,size):
        wx.Frame.__init__(self,parent, id,title,position, size)

        ## Set up the MenuBar

        MenuBar = wx.MenuBar()

        file_menu = wx.Menu()
        file_menu.Append(ID_OPEN, "O&pen","Open bitmap")
        file_menu.Append(ID_DIR, "Open directory\tCtrl+O")
        file_menu.Append(ID_EXIT_MENU, "E&xit","Terminate the program")
        wx.EVT_MENU(self, ID_EXIT_MENU,       self.OnQuit)
        wx.EVT_MENU(self, ID_OPEN,       self.OnOpen)
        wx.EVT_MENU(self, ID_DIR,       self.OnOpenDir)
        MenuBar.Append(file_menu, "&File")

        draw_menu = wx.Menu()
        draw_menu.Append(ID_DRAWTEST_MENU, "&Init\tF5","Initiate codebook vectors")
        wx.EVT_MENU(self, ID_DRAWTEST_MENU,self.InitSVQ)
        draw_menu.Append(ID_DRAWMAP_MENU, "Run SVQ on each image\tF6","")
        wx.EVT_MENU(self, ID_DRAWMAP_MENU,self.RunSVQ)
        draw_menu.Append(ID_RUNCBSVQ_MENU, "Run SVQ on codebook vectors\tF7","")
        wx.EVT_MENU(self, ID_RUNCBSVQ_MENU,self.RunCbSVQ)
        draw_menu.Append(ID_CLEAR_MENU, "&Clear","Clear the canvas")
        wx.EVT_MENU(self, ID_CLEAR_MENU,self.Clear)
        MenuBar.Append(draw_menu, "&Run")


        view_menu = wx.Menu()

        help_menu = wx.Menu()
        help_menu.Append(ID_ABOUT_MENU, "&About",
                                "More information About this program")
        wx.EVT_MENU(self, ID_ABOUT_MENU,      self.OnAbout)
        MenuBar.Append(help_menu, "&Help")

        self.SetMenuBar(MenuBar)

        self.CreateStatusBar()
        self.SetStatusText("")

        wx.EVT_CLOSE(self, self.OnCloseWindow)

        wx.EVT_RIGHT_DOWN(self, self.RightButtonEvent)

        self.Canvas = NavCanvas.NavCanvas(self,-1,(750,600),
                                  Debug = False,
                                  BackgroundColor = "Black").Canvas
        self.Canvas.NumBetweenBlits = 1000
        self.Show(True)

        #self.DrawSVQ(None)
        return None

    def RightButtonEvent(self,event):
        print "Right Button has been clicked in DrawFrame"
        print "coords are: %i, %i"%(event.GetX(),event.GetY())
        event.Skip()

    def OnAbout(self, event):
        dlg = wx.MessageDialog(self, "-----------About---------","About Me", wx.OK | wx.ICON_INFORMATION)
        dlg.ShowModal()
        dlg.Destroy()

    def ZoomToFit(self,event):
        self.Canvas.ZoomToBB()

    def Clear(self,event = None):
        self.Canvas.ClearAll()
        self.Canvas.Draw()

    def OnQuit(self,event):
        self.Close(True)

    def OnCloseWindow(self, event):
        self.Destroy()
        
    def OnOpen(self,event):
        dialog = wx.FileDialog ( None, style = wx.OPEN )
        if dialog.ShowModal() == wx.ID_OK:
            self.bmp = wx.Bitmap(dialog.GetPath())
        dialog.Destroy()
        self.InitSVQ()

    def OnOpenDir(self,event):
        dialog = wx.DirDialog(None,defaultPath='C:\Users\Kamil\Documents\NetBeansProjects\kamillo-ma-thesis-svq\series')
        if dialog.ShowModal() == wx.ID_OK:
            self.images = self.ReadAllImages(dialog.GetPath())
            self.AddImagesToCanvas(self.images)
        dialog.Destroy()

    def AddImagesToCanvas(self,images):
        position = [-375,300]
        #750 / 5
        for img in images:
 
            self.Canvas.AddScaledBitmap(img,position[:],300,'tl',InForeground=False)
            position[0] += img.GetWidth()
            if (images.index(img)+1)%5 == 0:
                position[0] = -375
                position[1] -= img.GetHeight()
        self.Canvas.ZoomToBB()
        #self.Canvas.Draw()
        
    ##TODO Polaczyc w jednej petelce AddImagesToCanvas InitSVQ i ...

    def InitSVQ(self,event = None):
        position = [-375,300]
        self.svq = []
        self.cbvecs = []
        Canvas = self.Canvas
        for img in self.images:
            
            self.svq.append( SVQ(20,self.GetPoints(img,position[:]),0.002,0.5) ) #0.0009
            #points = self.svq[-1].initCodeBook(1,True,[position[0],position[0]+img.GetWidth()],[position[1],position[1]-img.GetHeight()])
            points = self.svq[-1].initCodeBook(1,True)
            moved_points = self.MovePoints(points, position[:])
            self.cbvecs.append(self.Canvas.AddPointSet(moved_points,Color='Red',Diameter = 3,InForeground = True))
            Canvas.ZoomToBB()
            position[0] += img.GetWidth()
            if (self.images.index(img)+1)%5 == 0:
                position[0] = -375
                position[1] -= img.GetHeight()

    def MovePoints(self,points,position):
        new_points = []
        for i in range(len(points)):
            new_points.append([])
            for p in range(len(points[i])):
                new_points[i].append([])
                new_points[i][p].append(points[i][p][0]+position[0])
                new_points[i][p].append(points[i][p][1]*(-1) + position[1])
        return new_points

    def RunSVQ(self,event = None):
        self.ShapeVec = []
        start = clock()
        position = [-375,300]
        for s in self.svq:
            self.ShapeVec.append([])
            times = 5000
            eta0 = s.eta
            start2 = clock()
            for i in range(times):
                o = s.moveCodeBook(s.calcF(s.pickDataPoint()))
                #self.cbvecs[self.svq.index(s)].SetPoints(o)
                s.eta = eta0 * (times - i)/times
                #self.Canvas.Draw()
                wx.GetApp().Yield(True)
            self.cbvecs[self.svq.index(s)].SetPoints(self.MovePoints(o,position[:]))
            position[0] += self.images[0].GetWidth()
            if (self.svq.index(s)+1)%5 == 0:
                position[0] = -375
                position[1] -= self.images[0].GetHeight()
            print clock() - start2
            self.Canvas.Draw()
            for points in o:
                for point in points:
                    self.ShapeVec[-1].append(point)
            #s.saveLog("svq.txt")

        #dlg = wx.MessageDialog(self, "Running the svq algorithm took %f seconds"%(clock() - start),"Timing", wx.OK | wx.ICON_INFORMATION)
        #dlg.ShowModal()
        #dlg.Destroy()
        #print "running the svq algorithm took %f seconds"%(clock() - start)
        self.Canvas.ZoomToBB()

    def RunCbSVQ(self, event = None):
        self.Canvas.ClearAll()
        colors = ["Red","Blue","Green","Yellow"]
        times = 5000
        final = []
        cb_svq = SVQ(4,self.ShapeVec[:],0.002,0.5) #0.0002
        dziendobry = cb_svq.Data
        #m = cb_svq.initCodeBook(len(self.ShapeVec[0]), False)
        m = cb_svq.initCodeBook2()
        bbPoints = [[-10,-310],[-10,0],[1210,-310],[1210,0]]
        
        for img in m:
                final.append(self.Canvas.AddPointSet(img,Color=colors[m.index(img)],Diameter = 3,InForeground = True))
                #mm = self.MovePoints(deepcopy([img]),[m.index(img) * 300,0])
                #bbPoints += mm
        bb = BBox.fromPoints(bbPoints)
        self.Canvas.ZoomToBB(bb)
        start = clock()
        eta0 = cb_svq.eta
        for i in range(times):
            m = cb_svq.moveImgCodeBook(cb_svq.calcF(cb_svq.pickData()))
            cb_svq.eta = eta0 * (times - i)/times
            for j in final:
                mm = self.MovePoints(m,[final.index(j) * 300,0])
                j.SetPoints(mm[final.index(j)])
            self.Canvas.ZoomToBB(bb)
            #self.Canvas.Draw()
            wx.GetApp().Yield(True)
        self.Canvas.ZoomToBB(bb)
        print start - clock()
        #cb_svq.saveLog('svq2.txt')

    def GetPoints(self,image,move):
        points = []
        #image = bmp.ConvertToImage()
        for x in range(image.GetWidth()):
            for y in range(image.GetHeight()):
                if image.GetRed(x,y) == image.GetGreen(x,y) == image.GetBlue(x,y) == 255:
                    #points.append([(x-300),-1*(y-300)])
                    #points.append([x+move[0],-1*y+move[1]])
                    points.append([x,y])
        return points



    def ReadPoints(self,filename):
        input = []
        file = open(filename)
        lines = file.readlines()
        for line in lines:
            floated = []
            splitted = line.split(" ")
            #for s in splitted:
            #    s = int(s)
            #    floated.append(s)
            input.append([int(splitted[0]),int(splitted[1])])
        return input

    def ReadAllImages(self,dir):
        images = []
        for subdir,dir,files in os.walk(dir):
            for file in sorted(files):
                if 'svn' not in str(subdir)+ '/' + str(file):
                    print str(subdir)+ '/' + str(file)
                    images.append( wx.Image(str(subdir)+ '/' + str(file)) )
        return images

class DemoApp(wx.App):
    def OnInit(self):
        wx.InitAllImageHandlers()
        frame = DrawFrame(None, -1, "Soft Vector Quantization",wx.DefaultPosition, (750,600) )

        self.SetTopWindow(frame)

        return True


if __name__ == "__main__":
    try:
        import psyco
        psyco.log()
        psyco.full()
    except:
        print "could not import psyco"

    app = DemoApp(0)
    app.MainLoop()











